﻿using GDIForm;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AEBailan
{
    public partial class Form1 : GDIForm.GDIForm
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            addStage(1.25, 3.625, new FuStage(320, 180, 240));
            addStage(2.125, 3.2, new FuStage(520, 180, 240));
            addStage(2.975, 3.2, new FuStage(120, 180, 240));
            addStage(3.625, 3.8, new FuStage(320, 180, 320));
            addStage(3.8, 4.18, new FuStage(180, 180, 320));
            addStage(3.8, 4.18, new FuStage(640-180, 180, 320));
            addStage(4.18,4.625, new FuStage(320, 180, 320));
            addStage(4.625,6.175, new FuStage(320, 180, 320) { rotate = 180});
            addStage(6.175, 7.875, new FuSpinStage(320, 180, 320));
            addStage(7.875,9.5625, new FuSpinStage(180, 180, 320));
            addStage(7.875,9.5625, new FuSpinStage(640-180, 180, 320));
            addStage(9.625,10.6, new FirecrackStage(320-80,40));
            addStage(9.975,10.9, new FirecrackStage(120-80,40));
            addStage(10.4,11.4, new FirecrackStage(520-80,40));

            addStage(11.4, 12.85, new LanternStage(0,200,540,200,0,0,250));
            addStage(12.85, 14.85, new LanternStage(540,200,0,200,0,3600,250));

            addStage(14.84, 16.25, new LanternStage(640, 200, 100, 200, 0, 0, 250));
            addStage(16.25, 18.125, new LanternStage(100, 200, 640, 200, 0, 3600, 250));

            addStage(18.125, 18.75, new LanternStage(640, 200, 320, 200, 0, 0, 250));
            addStage(18.75, 19.825, new LanternStage(320, 300, 320, 300, 0, 0, 450));

            addStage(19.825, 20.475, new LanternStage(300, 180, 320, 200, 0, 0, 250));
            addStage(20.475, 21.375, new LanternStage(320, 300, 320, 300, 0, 0, 450));

            addStage(21.375,23.2, new LanternStage(0, -160, 640,480, 0, 0, 380));

            Random rnd = new Random(114514);
            for(float s = 23.2f; s<=28.82f; s += 0.2f)
            {
                addStage(s, s+1, new FirecrackStage((int)(rnd.NextDouble() * 500), (int)(rnd.NextDouble() * 240)));
            }

            addStage(28.82, 44, new FuAnimStage(0, 120, 640, 120, 0, 0, 100));
            addStage(28.82, 44, new FuAnimStage(640, 180, 0, 180, 0, 1280, 140));
            addStage(28.82, 44, new FuAnimStage(640,360, 0, 180, 0, 12800, 140));
            addStage(28.82, 34, new FuAnimStage(0, 160, 320, 0, 0, 14400, 140));
            addStage(34, 40, new FuAnimStage(320,0, 640, 160, 0, 14400, 140));
            addStage(40, 44, new FuAnimStage(640, 160, 320, 360, 0, 14400, 140));

            addStage(41, 62.725, new FuAnimStage(320, 180, 320, 180, 0, 0, 200,600));
            addStage(33,49, new CharSlideStage());
            addStage(62.725, 64.875, new FuAnimStage(320, 180, 320, 180, 0, 0, 600,100));
            int[] pos = new int[] { 
                320 - 120,180-40,
                320 - 40,180-40,
                320 +40,180-40,
                320 + 120,180-40,
                320 - 80,180+40,
                320 ,180+40,
                320 + 80,180+40
            };
            Image[] chars = new Image[] {
                Properties.Resources.c1,
                Properties.Resources.c1,
                Properties.Resources.c2,
                Properties.Resources.c2,
                Properties.Resources.c3,
                Properties.Resources.c4,
                Properties.Resources.c5
            };
            for (float i = 0; i < 7; i++)
            {
                float len = (64.7f - 45.8f);
                float begin = 45.8f+ len / 7f * i;
                float mid = 45.8f + len / 7f * i + (len / 14f);
                float end = 45.8f + len / 7f * i + (len / 7f);
                int index = (int)i;

                addStage(45.8f, begin, new CharAnimStage(chars[index], pos[index * 2], pos[index * 2 + 1], 60, 60));
                addStage(begin, mid, new CharAnimStage(chars[index], pos[index * 2], pos[index * 2 + 1], 60, 120));
                addStage(mid, end, new CharAnimStage(chars[index], pos[index * 2], pos[index * 2 + 1], 120, 60));
                addStage(end, 9999, new CharAnimStage(chars[index], pos[index * 2], pos[index * 2 + 1], 60, 60));
            }

        }

        public override void beforeInit()
        {
            base.beforeInit();
        }

        public override void onInit(Graphics g)
        {
            base.onInit(g);
        }
        private int currentFrame = 0;
        private List<Stage> stageList = new List<Stage>();
        public void addStage(double begin, double end, Stage s)
        {
            s.BeginFrame = (int)(begin * 64f);
            s.EndFrame = (int)(end * 64f);
            stageList.Add(s);
        }
        
        public override void onDraw(Graphics g)
        {
            g.Clear(Color.White);
            String status = "Frame=" + currentFrame+", Stage=";
            List<Stage> stage = new List<Stage>();
            if (stageList.Count > 0)
            {
                stage.AddRange(stageList.Where(s => s.BeginFrame <= currentFrame && s.EndFrame > currentFrame));
            }
            if(stage.Count==0)
            {
                status += "<NULL>";
                g.Clear(Color.White);
            }
            else
            {
                stage.ForEach(s => {
                    status += s.GetType().Name+",";
                    s.onDraw(g, currentFrame - s.BeginFrame);
                });
            }
            this.Text = status;
            currentFrame++;
        }

    }
    #region renderBase
    public abstract class Stage {
        public int BeginFrame { get; set; }
        public int EndFrame { get; set; }


        public virtual void onDraw(Graphics g,int t)
        {

        }

    }

    public class Sprite { 
        
    }
    #endregion


    class FuStage : Stage
    {
        private int cx, cy, size;
        public int rotate = 0;
        public FuStage(int cx,int cy,int size)
        {
            this.cx = cx;this.cy = cy;this.size = size;
        }
        Bitmap fu = new Bitmap(Properties.Resources.fu, 320, 320);

        public override void onDraw(Graphics g, int t)
        {
            DrawUtils.drawRotateImg(g, fu, rotate, cx, cy,size,size);
        }
    }
    class FuSpinStage : Stage 
    {
        private int cx, cy, size;
        public FuSpinStage(int cx, int cy, int size)
        {
            this.cx = cx; this.cy = cy; this.size = size;
        }
        Bitmap fu = new Bitmap(Properties.Resources.fu,320,320);
       
        public override void onDraw(Graphics g, int t)
        {
            DrawUtils.drawRotateImg(g, fu, t * 20f, cx, cy, size, size);
        }
    }
    class FirecrackStage : Stage
    {
        private int x, y;
        private Bitmap fw = new Bitmap(Properties.Resources.fw, 95, 150);
        private Bitmap spark = new Bitmap(Properties.Resources.spark, 60, 45);
        public FirecrackStage(int x, int y)
        {
            this.x = x; this.y = y; 
        }

        public override void onDraw(Graphics g, int t)
        {
            int h =150 - 150 * t / (EndFrame - BeginFrame);
            if (h > 150) { h = 150; }
            if (h < 0) { h = 0; }
            g.DrawImage(fw, new Rectangle(x, y, 95, h), 0, 0, 95, h,GraphicsUnit.Pixel);
            g.DrawImage(spark, x + 30, y + 140);
        }
    }



    class LanternStage : Stage
    {
        private int beginX, beginY, endX, endY, beginR, endR,size;
        private Bitmap lantern = new Bitmap(Properties.Resources.lantern, 300, 600);
        public LanternStage(int beginX, int beginY, int endX, int endY, int beginR, int endR, int size)
        {
            this.beginX = beginX;
            this.beginY = beginY;
            this.endX = endX;
            this.endY = endY;
            this.beginR = beginR;
            this.endR = endR;
            this.size = size;
        }

        public override void onDraw(Graphics g, int t)
        {
            float ip = (float)t / (float)(EndFrame - BeginFrame);
            float x = beginX + ip * (endX - beginX);
            float y = beginY + ip * (endY - beginY);
            float r = beginR + ip * (endR - beginR);
            DrawUtils.drawRotateImg(g,lantern, r, x, y, size, size * 1.7f);
        }
    }


    class FuAnimStage : Stage
    {
        private int beginX, beginY, endX, endY, beginR, endR, size,endsize;
        internal Bitmap lantern = new Bitmap(Properties.Resources.fu, 300, 300);
        public FuAnimStage(int beginX, int beginY, int endX, int endY, int beginR, int endR, int size)
        {
            this.beginX = beginX;
            this.beginY = beginY;
            this.endX = endX;
            this.endY = endY;
            this.beginR = beginR;
            this.endR = endR;
            this.size = size;
            this.endsize = size;
        }
        public FuAnimStage(int beginX, int beginY, int endX, int endY, int beginR, int endR, int size,int endsize)
        {
            this.beginX = beginX;
            this.beginY = beginY;
            this.endX = endX;
            this.endY = endY;
            this.beginR = beginR;
            this.endR = endR;
            this.size = size;
            this.endsize = endsize;
        }
        public override void onDraw(Graphics g, int t)
        {
            float ip = (float)t / (float)(EndFrame - BeginFrame);
            float x = beginX + ip * (endX - beginX);
            float y = beginY + ip * (endY - beginY);
            float r = beginR + ip * (endR - beginR);
            float s = size + ip * (endsize - size);
            DrawUtils.drawRotateImg(g, lantern, r, x, y, s, s );
        }
    }


    class CharSlideStage : Stage
    {
        private int beginX, beginY, endX, endY, beginR, endR, size, endsize;
        private Bitmap lantern = new Bitmap(Properties.Resources.charslide1, 160, 120);
        public CharSlideStage()
        {
            beginX = 640;
            endX = -160;
            beginY = endY = 80;
            beginR = endR = 0;
        }
        
        public override void onDraw(Graphics g, int t)
        {
            float ip = (float)t / (float)(EndFrame - BeginFrame);
            float x = beginX + ip * (endX - beginX);
            float y = beginY + ip * (endY - beginY);
            float r = beginR + ip * (endR - beginR);
            DrawUtils.drawRotateImg(g, lantern, r, x, y, 160,120);
        }
    }

    class CharAnimStage : Stage
    {
        private int beginX, beginY, endX, endY, beginR, endR, size, endsize;
        internal Bitmap lantern = new Bitmap(Properties.Resources.fu, 300, 300);

        public CharAnimStage(Image bmp,int x,int y, int size, int endsize)
        {
            this.lantern = new Bitmap(bmp, 80, 80);
            this.beginX = x;
            this.beginY =y;
            this.endX = x;
            this.endY =y;
            this.beginR = 0;
            this.endR = 0;
            this.size = size;
            this.endsize = endsize;
        }
        public override void onDraw(Graphics g, int t)
        {
            float ip = (float)t / (float)(EndFrame - BeginFrame);
            float x = beginX + ip * (endX - beginX);
            float y = beginY + ip * (endY - beginY);
            float r = beginR + ip * (endR - beginR);
            float s = size + ip * (endsize - size);
            DrawUtils.drawRotateImg(g, lantern, r, x, y, s, s);
        }
    }

}
